package pl.vm.domain;

import java.util.HashSet;
import java.util.Set;

import pl.vm.domain.exceptions.TeamIsNotValidException;
import pl.vm.domain.interfaces.Round;
import pl.vm.domain.interfaces.TeamManager;
import pl.vm.utils.ObjectCloner;

public class TeamManagerImpl implements TeamManager {

	private Seazon seazon;
	private Set<VirtualTeam> teams = new HashSet<>();
	private Set<OfficialTeam> officialTeams = new HashSet<>();

	public TeamManagerImpl(Seazon seazon) {
		this.seazon = seazon;
	}

	@Override
	public boolean addTeam(VirtualTeam team) {
		return teams.add(team);
	}

	@Override
	public void registerTeam(VirtualTeam team) {
		team.registerTeam();
		addTeamToCurrentRound(team);
	}

	private boolean addTeamToCurrentRound(VirtualTeam team) {
		Round currentRound = seazon.getRoundManager().getCurrentRound();
		if (currentRound != null && team.isTeamRegistered()) {
			try {
				return currentRound.addTeam((VirtualTeam) ObjectCloner
						.deepCopy(team));
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}
		return false;
	}

	@Override
	public VirtualTeam getTeam(String name) {
		for (VirtualTeam team : teams) {
			if (team.getName().equals(name)) {
				return team;
			}
		}
		return null;
	}

	@Override
	public boolean deleteTeam(VirtualTeam team) {
		return teams.remove(team);
	}

	@Override
	public Set<VirtualTeam> getVirtualTeams() {
		return teams;
	}

	@Override
	public Set<VirtualTeam> getTeamsOwnedBy(Owner owner) {
		Set<VirtualTeam> vteams = new HashSet<>();
		for (VirtualTeam team : teams) {
			if (team.getOwner().equals(owner)) {
				vteams.add(team);
			}
		}
		return vteams;
	}

	@Override
	public Set<OfficialTeam> getOfficialTeams() {
		return officialTeams;
	}

	@Override
	public boolean changeTeam(VirtualTeam oldTeam, VirtualTeam newTeam) {
		this.teams.remove(oldTeam);
		return this.teams.add(newTeam);
	}

	@Override
	public boolean addOfficialTeam(OfficialTeam team)
			throws TeamIsNotValidException {
		validateOfficialTeam(team);
		return officialTeams.add(team)
				&& seazon.getAllPlayers().addAll(team.getPlayers());
	}

	/* check if the same player exists in a team that is already added */
	private void validateOfficialTeam(OfficialTeam team)
			throws TeamIsNotValidException {
		if (officialTeams.contains(team)) {
			throw new TeamIsNotValidException("Team: " + team.getName()
					+ ", already exists");
		}
		for (OfficialTeam addedTeam : officialTeams) {
			for (Player playerInAddedTeam : addedTeam.getPlayers()) {
				if (team.getPlayers().contains(playerInAddedTeam)) {
					throw new TeamIsNotValidException("Team: " + team.getName()
							+ ", has player: "
							+ playerInAddedTeam.getLastName()
							+ ", which also exists in " + addedTeam.getName());
				}
			}
		}
	}

}
